// pages/tools/expression-calculator/expression-calculator.js
Page({

    /**
     * 页面的初始数据
     */
    data: {
        placeholder:"[按键]或[直接打字]，如1/(4*3)^0.5",
        exp:"",
        result:"计算结果将显示在这里",
        keys:[
            ["clear","(",")","÷"],
            ["7","8","9","×"],
            ["4","5","6","-"],
            ["1","2","3","+"],
            ["0",".","^","="],
        ]
    },
    onShareAppMessage: function (res) {
        return {
          title: '快来看看学长开发的万能基物实验小程序！',
          path: 'pages/index/index',
          imageUrl: 'https://s1.ax1x.com/2020/07/25/aSICY4.jpg',
          success: function (res) {
            console.log('成功分享', res)
          }
        }
    },

    tap(e) {
        var dataset = e.currentTarget.dataset
        this.setData({
            exp:this.data.exp+this.data.keys[dataset.i][dataset.j]
        })  
    },

    longtapbracket(e) {
        if (e.currentTarget.dataset.j == 1) {
            this.setData({
                exp:this.data.exp+"["
            })
        } else {
            this.setData({
                exp:this.data.exp+"]"
            })
        }
        
    },

    clear(e) {
        this.setData({
            exp:""
        })
    },

    delete(e) {
        this.setData({
            exp:this.data.exp.substring(0,this.data.exp.length-1)
        })
    },

    input(e) {
        this.setData({
            exp:e.detail.value
        })
    },

    calculate() {
        var exp = this.data.exp
        console.log(exp)
        var ans
        try {
            value = evalRpn(dal2Rpn(exp))
            if (isNaN(value)) {
                ans = "Not a number！"
            }
            else {
                ans = exp + " = " + value
            }
        } catch (error) {
            console.log(error)
            if (error instanceof TypeError) {
                ans = "括号不匹配！"
            } else if (error instanceof SyntaxError) {
                ans = "非法表达式！"
            }
        }
        if (exp == "") {
            ans = "请输入表达式！"
        }
        this.setData({
            result : ans
        })
        console.log(this.result)
      },

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad: function (options) {

    },

    /**
     * 生命周期函数--监听页面初次渲染完成
     */
    onReady: function () {

    },

    /**
     * 生命周期函数--监听页面显示
     */
    onShow: function () {

    },

    /**
     * 生命周期函数--监听页面隐藏
     */
    onHide: function () {

    },

    /**
     * 生命周期函数--监听页面卸载
     */
    onUnload: function () {

    },

    /**
     * 页面相关事件处理函数--监听用户下拉动作
     */
    onPullDownRefresh: function () {

    },

    /**
     * 页面上拉触底事件的处理函数
     */
    onReachBottom: function () {

    },
})

function isOperator(value) {
    var operatorString = "+-*/()^";
    return operatorString.indexOf(value) > -1
}
 
function getPrioraty(value) {
    switch (value) {
        case '+':
        case '-':
            return 1;
        case '*':
        case '/':
            return 2;
        case '^':
            return 3;
        default:
            return 0;
    }
}
 
function prioraty(o1, o2) {
    return getPrioraty(o1) <= getPrioraty(o2);
}

String.prototype.replaceAll=function(f,e){//吧f替换成e
    var reg=new RegExp(f,"g"); //创建正则RegExp对象   
    return this.replace(reg,e); 
}

function preprocess(exp) {
    console.log("before: " + exp)
    if (exp[0] == "-") {
        exp = "0" + exp
    }
    exp = exp.replaceAll("\\(-","(0-")
    exp = exp.replaceAll("×","*")
    exp = exp.replaceAll("÷","/")
    exp = exp.replaceAll("\\[","(")
    exp = exp.replaceAll("\\]",")")
    console.log("after: " + exp)
    return exp
}
 
function dal2Rpn(exp) {
    exp = preprocess(exp)
    var inputStack = [];
    var outputStack = [];
    var outputQueue = [];
    let res = '';
    for (var i = 0, len = exp.length; i < len; i++) {
      var cur = exp[i];
      if (cur != ' ') {
        res = res + cur;
        if (i + 1 < exp.length) {
          if (isOperator(exp[i])) {
            inputStack.push(res);
            res = ''
          } else {
            if (isOperator(exp[i + 1])) {
              inputStack.push(res);
              res = ''
            }
          }
        } else {
          inputStack.push(res);
          res = ''
        }
      }
    }
 
    while (inputStack.length > 0) {
        var cur = inputStack.shift();
        if (isOperator(cur)) {
            if (cur == '(') {
                outputStack.push(cur);
            } else if (cur == ')') {
                var po = outputStack.pop();
                while (po != '(' && outputStack.length > 0) {
                    outputQueue.push(po);
                    po = outputStack.pop();
                }
                if (po != '(') {
                    throw new TypeError("error: unmatched ()");
                }
            } else {
                while (prioraty(cur, outputStack[outputStack.length - 1]) && outputStack.length > 0) {
                    outputQueue.push(outputStack.pop());
                }
                outputStack.push(cur);
            }
        } else {
            outputQueue.push(new Number(cur));
        }
    }
 
    if (outputStack.length > 0) {
        if (outputStack[outputStack.length - 1] == ')' || outputStack[outputStack.length - 1] == '(') {
            throw new TypeError("error: unmatched ()");
        }
        while (outputStack.length > 0) {
            outputQueue.push(outputStack.pop());
        }
    }
 
    return outputQueue;
 
}

function evalRpn(rpnQueue) {
    var outputStack = [];
    while (rpnQueue.length > 0) {
        var cur = rpnQueue.shift();
 
        if (!isOperator(cur)) {
            outputStack.push(cur);
        } else {
            if (outputStack.length < 2) {
                throw new SyntaxError("unvalid stack length");
            }
            var sec = outputStack.pop();
            var fir = outputStack.pop();
 
            outputStack.push(getResult(fir, sec, cur));
        }
    }
    if (outputStack.length != 1) {
        throw new SyntaxError("unvalid expression");
    } else {
        return outputStack[0];
    }
}
function getResult(first, second, operator) {
    var result = 0;
    switch (operator) {
        case '+':
            result = first + second;
            break;
        case '-':
            result = first - second;
            break;
        case '*':
            result = first * second;
            break;
        case '/':
            result = first / second;
            break;
        case '^':
            result = first ** second;
            break;
        default:
            return 0;
    }
 
    //浮点数的小数位超过两位时，只保留两位小数点
    function formatFloat(f, digit) {
        //pow(10,n) 为 10 的 n 次方
        var m = Math.pow(10, digit);
        return parseInt(f * m, 10) / m;
    }
    return (formatFloat(result, 5));
}
